/*
 *  InformationRetrievalApp.java
 *
 *  Copyright (c) 1998-2003, The University of Sheffield.
 *
 *  This file is part of GATE (see http://gate.ac.uk/), and is free
 *  software, licenced under the GNU Library General Public License,
 *  Version 2, June 1991 (in the distribution as file licence.html,
 *  and also available at http://gate.ac.uk/gate/licence.html).
 *
 *  Marin Dimitrov, 27/Jan/2003
 *
 *  $Id: InformationRetrievalApp.java,v 1.4 2004/12/14 14:36:24 niraj Exp $
 */


import java.util.*;
import java.io.*;
import java.net.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import gate.*;
import gate.annotation.NodeImpl;
import gate.creole.ANNIEConstants;
import gate.util.Err;
import gate.util.Out;

import gate.util.GateException;
import gate.creole.ResourceInstantiationException;
import gate.creole.SerialAnalyserController;
import gate.creole.ir.*;
import gate.creole.ir.lucene.*;
import gate.creole.tokeniser.DefaultTokeniser;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;

public class InformationRetrievalApp {

    //Thư mục lưu trữ index
  private static String INDEX_LOCATION = "c:/temp/lucene";
  
  //Thư mục lưu trữ datastore
  private static String SERIAL_DATASTORE_PATH = "file:///c:/temp/gate_corpus";
  //NOTE: Thư mục phải trống

  public InformationRetrievalApp() {
  }

  public static void main(String[] args) throws MalformedURLException {

    InformationRetrievalApp irApp = new InformationRetrievalApp();

    //Khởi tạo GATE
    //    
    try {
      Gate.init();
            File gateHome = Gate.getGateHome();
            File pluginsHome = new File(gateHome, "plugins");
            Gate.getCreoleRegister().registerDirectories(new File(pluginsHome, "ANNIE").toURL());
      Out.prln("GATE initialised...");
    }
    catch (GateException gex) {
      Err.prln("cannot initialise GATE...");
      gex.printStackTrace();
      return;
    }

    try{
        
        SerialAnalyserController annieController = (SerialAnalyserController)Factory.createResource("gate.creole.SerialAnalyserController", Factory.newFeatureMap(), 
                                                                Factory.newFeatureMap(), "ANNIE_" + Gate.genSym());
        //DefaultTokeniser token = (DefaultTokeniser)Factory.createResource("gate.creole.tokeniser.DefaultTokeniser", Factory.newFeatureMap());
        for(int i = 0; i < ANNIEConstants.PR_NAMES.length; i++) {
            FeatureMap params = Factory.newFeatureMap(); // use default parameters
 ProcessingResource pr = (ProcessingResource)
         Factory.createResource(ANNIEConstants.PR_NAMES[i], params);
      // add the PR to the pipeline controller
        annieController.add(pr);
        }
        
        
      //1. create and open a serial data store
      //DataStore sds = Factory.createDataStore("gate.persist.SerialDataStore", SERIAL_DATASTORE_PATH);
      //sds.open();
        
      ////1. open a serial data store
        DataStore sds = Factory.openDataStore("gate.persist.SerialDataStore", SERIAL_DATASTORE_PATH);
        sds.open();
      //2. create transient corpus with docs
      Corpus corpus =  irApp.createTestCorpus();
      annieController.setCorpus(corpus);
      annieController.execute();
      //3. serialize corpus in Serial datastore
      Corpus serialCorpus = (Corpus)sds.adopt(corpus,null);

      //4. sync datastore
      sds.sync(serialCorpus);

      //5. index the serialized corpus
      IndexedCorpus indexedCorpus = (IndexedCorpus)serialCorpus;

      //Khởi tạo Index 
      DefaultIndexDefinition did = new DefaultIndexDefinition();
      // Sử dụng kỹ thuật Lucene IR
      //  
      did.setIrEngineClassName(gate.creole.ir.lucene.LuceneIREngine.class.getName());
      
      //Xác định vị trí index
      did.setIndexLocation(INDEX_LOCATION);
      
      //Xác định trường index
      did.addIndexField(new IndexField("content", new DocumentContentReader(), false));
      //did.addIndexField(new IndexField("kind", new ProperyReader(), false));
      
      indexedCorpus.setIndexDefinition(did);

      //5.5 ask the IndexManager to create the index (delete it beforehand if already existing)
      indexedCorpus.getIndexManager().deleteIndex();
      indexedCorpus.getIndexManager().createIndex();
      indexedCorpus.getIndexManager().optimizeIndex();

      //7. search in index

      //7.2.  create the proper Search subclass
      //    since we're using the Lucene IR engine, use LuceneSearch
      Search search = new LuceneSearch();
      //    the Search instance needs to know which corpus to search
      search.setCorpus(indexedCorpus);
      
     String  query = "lack USA";//    ...Câu truy vấn tìm kiếm nhập vào là: "lack USA"
     query q = new query(query);
     
            
      irApp.timKiem(sds, search, q.createQueryString());//    ...Câu truy vấn chuẩn hóa là: +content:\"lack\"+content:\"USA\"
      irApp.searchNode(q.getArrayQuery());      
      Out.prln("done...");

    }
    catch(Exception ex) {
      ex.printStackTrace(Err.getPrintWriter());
    }

  }

  public void timKiem(DataStore sds, Search search, String query) throws ParserConfigurationException, SAXException, IOException
  {
      try
      {
      //Thực thi câu truy vấn
      QueryResultList res = search.search(query);
      //Trả về kết quả
      Iterator it = res.getQueryResults();
      //Xem kết quả
      while (it.hasNext()) {
        QueryResult qr = (QueryResult) it.next();
        float score = qr.getScore();
        //
        //  Lấy thông tin về tài liệu liên quan
        Document resultDoc = (Document) sds.getLr("gate.corpora.DocumentImpl", qr.getDocumentID());
        Out.prln("Query: Tên tài liệu = " + resultDoc.getName()); 
        Out.prln("Query: Tần suất xuất hiện  = " + score);
        
        // Output kết quả tìm kiếm ra file XML, lưu tại project thực thi
        File file = new File("xml/" + resultDoc.getName().substring(0, resultDoc.getName().length() - 4)+".xml");
        // if file doesnt exists, then create it
	if (!file.exists()) {
                    file.createNewFile();
	}
        
        FileWriter writer = new FileWriter(file.getAbsoluteFile());
        writer.write(resultDoc.toXml());
        writer.close(); 
        }
        
        Out.prln("------------");
      }
      catch(Exception ex)
      {
          ex.printStackTrace(Err.getPrintWriter());
      }
  }
     
  public void searchNode(String[] array_query) throws ParserConfigurationException, SAXException, IOException, TransformerConfigurationException, TransformerException
  {
        File folder = new File("xml");
        File[] listFile = folder.listFiles();
        for(int k = 0; k< listFile.length; k++){
            if(listFile[k].isFile()){
                
                File file  = new File(listFile[k].getPath());
                CreateXML xml = new CreateXML(file);
                String text = xml.getTextNode();
        
                xml.removeAnnotationSet();
                
                for(int j = 0; j<array_query.length; j++){
                formatText ft = new formatText(text);
                
                String[] left_str = ft.leftContent(array_query[j]);
                String[] right_str = ft.rightContent(array_query[j]);
                int count = ft.countFrequency(array_query[j]);
                for(int i = 0; i< count; i++){
                    xml.createElementResult(count, left_str[i], array_query[j], right_str[i]);
                }
            
                xml.createFileResult();
            }
            }
        }
  }
  
  public Corpus createTestCorpus()
    throws MalformedURLException, ResourceInstantiationException {
      
      //Tạo 1 corpus với những tài liệu trên
    Corpus result = Factory.newCorpus("test corpus");
    assert result != null;
    
    File folder = new File("c:/temp/document");
    File[] listFile = folder.listFiles();
    
    for(int i =0; i<listFile.length; i++)
    {
    Document doc = Factory.newDocument(new URL("file:///" + listFile[i].getPath()));
    doc.setName("Document_" + listFile[i].getName());
    assert doc!=null;
    result.add(doc);
    }
    return result;
  }

}